package cn.demo.app.gateway;

import cn.ifloat.brick.basic.common.toolkit.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.base.Joiner;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: float 2023/7/5 16:43
 */
public class SimpleFilter implements GatewayFilter, Ordered {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public int getOrder() {
        // -1 is response write filter, must be called before that
        return -2;
    }


    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        logger.info("global filter HttpResponseBody，processing response results");

        // 这里可以增加一些业务判断条件，进行跳过处理

        ServerHttpResponse response = exchange.getResponse();
        DataBufferFactory bufferFactory = response.bufferFactory();

        HttpHeaders headers = exchange.getRequest().getHeaders();
        headers.add("userInfO","{USER:FHASD ASDHSKJ AHLF }");
        headers.add("SERVER_REQUEST_CLIENT","GATEWAY");

//        response.writeWith(body->{
//            if (response.getStatusCode() != null && body instanceof Flux) {
//                Flux<? extends DataBuffer> fluxBody = Flux.from((Publisher<? extends DataBuffer>) body);
//                fluxBody.buffer().map(dataBuffers -> {
//                    DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
//                    DataBuffer dataBuffer = dataBufferFactory.join(dataBuffers);
////                    dataBuffer.
//                    byte[] content = new byte[dataBuffer.readableByteCount()];
////                    dataBuffer.read(content);
////                    DataBufferUtils.release(dataBuffer);
////                    List<String> encodingList = exchange.getResponse().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
////                    boolean zip = encodingList != null && encodingList.contains("gzip");
////                    String responseData = new String(content);
////                    String result = responseConversion(responseData);
////                    response.getHeaders().setContentLength(result.length());
////                    response.setStatusCode(HttpStatus.OK);
//                    logger.info("writeWith :{}",new String(content));
//                    return bufferFactory.wrap(content);
//                });
//            }
//        });


        // 响应装饰
        ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(response) {
            @Override
            public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
                logger.info("global filter HttpResponseBody，Response processing，getStatusCode={}", getStatusCode());
                if (getStatusCode() != null && body instanceof Flux) {
                    Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                    return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                        // 如果响应过大，会进行截断，出现乱码，看api DefaultDataBufferFactory
                        // 有个join方法可以合并所有的流，乱码的问题解决
                        DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
                        DataBuffer dataBuffer = dataBufferFactory.join(dataBuffers);
                        byte[] content = new byte[dataBuffer.readableByteCount()];
                        dataBuffer.read(content);
                        // 释放掉内存
                        DataBufferUtils.release(dataBuffer);

                        List<String> encodingList = exchange.getResponse().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
                        boolean zip = encodingList != null && encodingList.contains("gzip");
                        // responseData就是response的值，就可查看修改了
//                        String responseData = getResponseData(zip, content);
//                        String responseData = "{\"code\":\"123\"}";
                        String responseData = new String(content);

//                        JSONObject jsonObject = JSON.parseObject(responseData);

                        System.out.println(responseData);
                        // 重置返回参数
//                        String result = responseConversion(responseData);
//                        byte[] uppedContent = getUppedContent(zip, result);
                        response.getHeaders().setContentLength(responseData.length());
                        response.setStatusCode(HttpStatus.OK);

                        return bufferFactory.wrap("abcabcacb".getBytes());
                    }));
                }
                // if body is not a flux. never got there.
                return super.writeWith(body);
            }
        };
        // replace response with decorator
        return chain.filter(exchange.mutate().response(decoratedResponse).build());
//        return chain.filter(exchange).then();
    }

    private String responseConversion(String result) {
        try {
            logger.info("响应结果为：{}", result);
            // 返回值基本数据类型、返回对象、数组的判断
//            RestResponse<Object> restResponse = RestResponse.ok(result);
            //
//            return JSONUtil.toJsonStr(restResponse);
            return result;
        } catch (Exception e) {
            logger.error("响应包装转换失败，异常信息为：", e);
            return result;
        }
    }

//    private String getResponseData(boolean zip, byte[] content) {
//        String responseData;
//        if (zip) {
////            responseData = GZIPUtils.uncompressToString(content);
//        } else {
////            responseData = new String(content, StandardCharsets.UTF_8);
//        }
//        return responseData;
//    }


//    private byte[] getUppedContent(boolean zip, String result) {
//        byte[] uppedContent;
//        if (zip) {
//            uppedContent = GZIPUtils.compress(result);
//        } else {
//            uppedContent = result.getBytes(StandardCharsets.UTF_8);
//        }
//        return uppedContent;
//    }

}
